using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;

namespace StyleCopContrib.CustomRules
{
	/// <summary>
	/// This class act as the ServiceLocator pattern.
	/// </summary>
	public sealed class ServiceLocator
	{
		#region Fields

		private static ServiceLocator _instance;

		private readonly IDictionary<Type, object> _services;

		#endregion

		#region Constructor

		private ServiceLocator()
		{
			this._services = new Dictionary<Type, object>();
		}

		#endregion

		#region Methods

		/// <summary>
		/// Gets the service of the given type.
		/// </summary>
		/// <typeparam name="T">The service type.</typeparam>
		/// <returns>The service.</returns>
		[SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "API designed for type reference")]
		public static T GetService<T>()
		{
			return ServiceLocator.GetInstance().InternalGetService<T>();
		}

		/// <summary>
		/// Registers the service.
		/// </summary>
		/// <typeparam name="T">The service type.</typeparam>
		/// <param name="service">The service.</param>
		[SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "API designed for type reference")]
		public static void RegisterService<T>(object service)
		{
			ServiceLocator.GetInstance().InternalRegisterService<T>(service);
		}

		private T InternalGetService<T>()
		{
			object result;

			this._services.TryGetValue(typeof(T), out result);

			return (T)result;
		}

		private void InternalRegisterService<T>(object service)
		{
			this._services.Add(typeof(T), service);
		}

		private static ServiceLocator GetInstance()
		{
			if (ServiceLocator._instance == null)
			{
				ServiceLocator._instance = new ServiceLocator();
			}

			return ServiceLocator._instance;
		}

		#endregion
	}
}